home *** CD-ROM | disk | FTP | other *** search
/ AGA Toolkit '97 / The AGA Toolkit '97.iso / programming / asm / popt / popt.doc < prev    next >
Encoding:
Text File  |  1996-09-07  |  16.7 KB  |  366 lines

  1.                popt: Peephole OPTimizer
  2.                ------------------------
  3.                    V1.00 beta
  4.  
  5.              (c) by Samuel DEVULDER, 1995.
  6.  
  7. DESCRIPTION (short):
  8. -------------------
  9.  
  10.     Popt is an  optimizer  of  assembly  sourcefile.  It  does  various
  11.     standard peephole optimizations by pattern-matching. It ranges  from  1
  12.     intruction lookahead to 3 and many more ! It makes more job than  usual
  13.     bluid-in assembler optimizer and uses data-flow analysis to find  which
  14.     register are used or not. With those  informations    it  is    capable  of
  15.     deleting intructions that are of no use and re-assigning  registers  to
  16.     produce a code of better quality/looking. It is specialy  powerfull  on
  17.     code produced by C-compilers (even those that optimize their code !).
  18.  
  19.     It is designed to keep the extra-code statements very much the same
  20.     as the original. Thus comments and pseudo-op are kept intact so that if
  21.     they bear special informations for the assembler  (for  debugging,  for
  22.     example), those are kept intact. In fact  it  makes  no  assumption  on
  23.     pseudo-op  and  only  work    on  real  micro-processor   operation-code.
  24.     Therefore, it is usefull with any  assembler  sourcefile  in  spite  of
  25.     their pseudo-op syntax and usage.
  26.  
  27. USAGE:
  28. -----
  29.  
  30.     Usage: popt [-revinfo] [flags] <inputfile.asm> [-o <outputfile.asm>]
  31.  
  32.     Valid optimizer flags are:
  33.     -d          : Debug
  34.     -v          : Verbose
  35.     -s          : Safe optimization only
  36.     -z          : Optimize size
  37.     -cr <REGMASK> : Set regs refs in jsr (def='')
  38.     -cs <REGMASK> : Set regs sets in jsr (def=D0/D1/A0/A1)
  39.     -ru <REGMASK> : Set regs used after rts (def=D0/D2-D7/A2-A6)
  40.     -4          : Optimize for 68040
  41.     -2          : Optimize for 68020/030
  42.     -ns          : Output new syntax
  43.     -nw          : Do not display warnings
  44.         -np           : Supress stack fixup
  45.         -ni           : Allow usage of new instructions for 68020+
  46.      -kc          : Keep lines only containing comments
  47.     -kl          : Keep unused label
  48.     -sl          : Put labels in separate lines
  49.     -h          : This usage (same as -? or ?)
  50.  
  51.     Use the -revinfo argument if you whish to  have  some  informations
  52.     about the program: Number of successful compilations done sofar, name &
  53.     size & date of the modules it is build of.
  54.  
  55.     Be sure that the "-o" flags is followed by the name of  the  output
  56.     file. This name can be concatenated with the "-o".  So  "-ofoo.asm"  is
  57.     the same as "-o foo.asm". If this flags is not used, the output file is
  58.     the same as the input file.
  59.  
  60.     Flags can be anywhere on the  command  line.  They  can  be  merged
  61.     together. So "-dvz" is like "-d -v -z". This can work  for  flags  that
  62.     expects an extra argument (such as "-o <filename>"), but  the  rest  of
  63.     the flag will be treated as the extra argument. So be carefull  because
  64.     "-dvoz foo.asm" will output a file called "z" ! The good way to do this
  65.     is to use "-dvzo foo.asm" or "-dvzofoo.asm" (ie. the 'o' letter must be
  66.     the last of the argument).
  67.  
  68.     Detailed description of the flags:
  69.  
  70.     -d:  Outputs some debug informations while optimizing,    as  well as
  71.          information in the ouputfile related to live/dead analysis (in
  72.          a comment preceded by ';'  on  each  line  containing  a  real
  73.          op-code). Use this for curiosity...  The  comment    is  of    the
  74.          form: ref=XXXX set=XXXX live=XXXX where  XXXX  stands  for  an
  75.          hexadecimal  number.  Those  numbers  represent   a   set     of
  76.          registers. Bit 1 (lsb) represents A0, Bit 7 represents A7, Bit
  77.          8: D0, Bit 15 (msb) is D7. The number in  ref=XXXX  represents
  78.          the registers referenced (bit set means a referenced register)
  79.          by the  instruction  on  that  line.  The    one  with  set=XXXX
  80.          represents registers that are set and the live=XXXX represents
  81.          registers that are alive for that instruction. This  can  help
  82.          to know why POPT did or did not do an optimization.
  83.  
  84.     -v:  Outputs some statistics about the optimizations  and  the file
  85.          beeing optimized.
  86.  
  87.     -s:  Avoid making optimizations that can make  your  program behave
  88.          wrongly. (It's hard to really guarantee this statement :-).
  89.  
  90.     -z:  Avoid optimizations that increase the size of the output (that
  91.          is to say, roughly, optimizations of mul operations).
  92.  
  93.     -4:  Perform specific optimizations  for  the  68040.  Note  that a
  94.          code optimized for a 68000 may work slower (proportionally) on
  95.          a 68040.
  96.  
  97.     -2:  Perform  specific    optimizations  for  the 68020/68030  micro-
  98.          processors. Same remark as for '-4' flag.
  99.  
  100.     -ru: Set registers that are used after    a  RTS    instruction.  Those
  101.          registers are those in which return values  of  functions    are
  102.          and registers not scratched by function  call  (ie.  registers
  103.          pushed  onto  the    stack  in  a  function).  By  default  only
  104.          D0/D2-D7/A2-A6 are assumed for that perpose. If you don't know
  105.          what registers your compiler use, or if you whish    to  make  a
  106.          safer optimization, use D0-D7/A0-A7 as <REGMASK>. <REGMASK> is
  107.          a register mask. A  register  mask  is  a    list  of  registers
  108.          separated by '/'. You can use a '-' between two  registers  to
  109.          describe  all  registers  betweens  those    two  (a  range   of
  110.          registers). For example D0-D2 is the same as D0/D1/D2.
  111.  
  112.     -cs: Set registers that are set (scratched) in jsr/bsr calls. Those
  113.          registers are supposed to be set by the code executed  by    the
  114.          jsr. Those registers include also the register(s)  that  bears
  115.          the return value of the function. By default, D0-D1/A0-A1    are
  116.          used as such scratched registers. If you wish to make a  safer
  117.          optimization, you should use an empty mask of  registers  (use
  118.          '' for that).
  119.  
  120.     -cr: Set registers that are used in jsr/bsr calls. Those  registers
  121.          are supposed to be used for passing variables  to    a  function
  122.          without using the stack. By default, no registers are  assumed
  123.          for that (empty <REGMASK>).  If  you  wish  to  make  a  safer
  124.          optimization, you can use D0-D7/A0-A6 as <REGMASK>.
  125.  
  126.     -ns: This  forces  POPT  to  output a  code  with the new  MOTOROLA
  127.          syntax.  With this,  -4(A5) will be printed as (-4,A5). Please
  128.          note that    the new  syntax  may  be  bad  interpreted by  your
  129.          assembler as a sub-mode of a new addressing mode and hence may
  130.          slow down your program !
  131.  
  132.     -nw: With that option, POPT will  not  complain  about    an  unknown
  133.          addressing mode or opcode. Use this if you  are  using  68020+
  134.          opcodes (like bitfields) and you know that POPT will  complain
  135.          about it (see BUG section for further explanations).
  136.  
  137.     -np: This option tells POPT to avoid stack optimisations.
  138.  
  139.         -ni: With that option, POPT will occasionaly use 68020 instructions
  140.              or addressing mode.
  141.  
  142.     -kc: This prevent POPT from deleting empty lines that consists only
  143.          of comments. NOTE: This can disable some optimisations.
  144.  
  145.     -kl: That makes POPT keep all labels. Even if some are unused.    Use
  146.          this if you code is to be included in an other  one  and  POPT
  147.          removes some labels (it can't figure which one must  be  kept,
  148.          because there is no xdef or so for that way of programming).
  149.  
  150.     -sl: POPT will put all your labels on separate lines. Use this    for
  151.          aesthetic reasons. Some people told me  that  they  think    the
  152.          optimized code is much more readable like that (Hello FLINT  !
  153.          :-).
  154.  
  155. MORE DESCRIPTION:
  156. ----------------
  157.  
  158.     We can describe peephole optimizations by saying that  the  program
  159.     looks for special pattern locally in the code  (with  a  window  of  1,
  160.     2,... contiguous instructions) and replace it by an other one  that  is
  161.     executed faster by the microprocessor.
  162.  
  163.     Those optimizations are safe for the data.  That  is  to  say  that
  164.     result (in the data/registers) of the sequence of instructions  do  not
  165.     change when replaced. However, those are not safe for the control flags
  166.     of the processor (i.e. some flags may be wrong when  some  instructions
  167.     are replaced), so the code may execute wrongly.  It  is  very  hard  to
  168.     combine optimizations with strict flags preservation, but popt does its
  169.     best to do so.
  170.  
  171.     By default it doesn't care about flags  preservation  (that  allows
  172.     more optimizations), but you  can  make  it  more  secure  by  avoiding
  173.     optimizations that might give wrong flags.    Anyway,  BE  WARNNED  THAT,
  174.     even so, OPTIMIZATIONS  ARE  NOT  100%  SECURE,  and  you  should  test
  175.     INTENSIVELY an optimized program to see if its behaviour is correct.  I
  176.     can tell you that most C-program are  ok,  since  they  don't  rely  on
  177.     strange flags (Carry, Halfbyte, Overflow, ...) and  on  flags  sets  by
  178.     instructions (the compiler puts tests instruction usually, so tests are
  179.     right).
  180.  
  181.     Although it does speed    optimizations,    you  can  prevent  it  from
  182.     optimizations that increase size.
  183.  
  184.     The data-flow analysis is used to determine for each instruction in
  185.     the code which register is dead or not. A register is said to  be  dead
  186.     in an intruction if its value is not used by some intructions that    can
  187.     be executed after the one considered. For example, register D0 is  dead
  188.     for instructions just before MOVE.L #0,D0 because the value  of  D0  is
  189.     about to be scratched by the move operation. A  register  that  is    not
  190.     dead is said to be (... guess !) alive. An operation that references D0
  191.     value brings it back to life.
  192.  
  193.     POPT uses well kwown peephole  optimisations  that  keep  the  data
  194.     intact such as quick move, additions, subtaction, replace .L  operation
  195.     by .W for A-registers, replace a MUL instruction by a  shift  one  (and
  196.     many more:    see  the  other  documentation    file  containing  the  list
  197.     (peephole.doc)) ... but it can do more by using the data-flow analysis.
  198.     For example, it can transform a CMPI  instruction  by  a  SUBQ  if    the
  199.     register is dead or suppress an instruction that sets a dead  register.
  200.     It can even find temporary-scrached registers to perform replacement of
  201.     MUL by SHIFT & ADD.
  202.  
  203.     In addition to    peephole  optimizations,  it  can  do  some  global
  204.     optimizations such as branch optimizations (branch to branch, branch to
  205.     next instruction,  branch  to  conditional    branch,  branch  inversion,
  206.     pre-computing  a  conditional  branch),   supression   of    LINK/UNLINK
  207.     instruction if the link'ed register is not  used  (good  for  low-level
  208.     routine in C !), deleting unused regs in MOVEM instruction and  merging
  209.     multiple labels (just for sourcefile  size  optimization,  good-looking
  210.     source and, actually, for internal purpouse :^) ).
  211.  
  212.     It can also replace a register by an other one to avoid silly moves
  213.     that usually occur in code generated by C  compilers.  For    example  it
  214.     replaces the sequence
  215.  
  216.         MOVE.L    D3,D1
  217.         LSL.L    D5,D1
  218.         ADD.L    D2,D1
  219.         MOVE.L    D1,D4
  220.     by
  221.         MOVE.L    D3,D4
  222.         LSL.L    D5,D4
  223.         ADD.L    D2,D4
  224.  
  225.     The code looks better, doesn't it ? And it takes one instruction less !
  226.     Those replacements are done independently of local windows. So they are
  227.     a kind of global optimizations. It    can  also  detect  when  A-register
  228.     pre-decrement  or  post-increment  modes  can  be  used  so  that  a  C
  229.     expression like a=*ptr++ can be  efficiently  translated  to  something
  230.     like MOVE.L (A0)+,D0 even if the compiler use a strange sequence like:
  231.  
  232.         MOVE.L    A0,A6
  233.         ADD.L    #4,A0
  234.         MOVE.L    (A6),D0
  235.  
  236.     POPT is able to simulate part of a code  to  avoid  an    unnecessary
  237.      test. Thus it can detect code  generated  by  for(;;)  statement  like
  238.      {short i,j;for(i=10;i--;++j);} (generated by DCC):
  239.  
  240.         MOVEQ    #10,D2
  241.         BRA    l4
  242.         l1
  243.         l2
  244.         ADDQ.W    #$01,D3
  245.         l4
  246.         MOVE.W    D2,D0
  247.         SUBQ.W    #$01,D2
  248.         TST.W    D0
  249.         BNE    l1
  250.  
  251.     and replace it by a very efficient code:
  252.  
  253.         MOVEQ    #9,D2
  254.         l1    ADDQ.W    #1,D3
  255.         l4    DBF    D2,l1
  256.  
  257.     Nice, isn't it ? (The test in the first iteration in the loop is always
  258.     true, so POPT removes the branch to l4 and replace 10 by 9 !).
  259.  
  260.     The 68040 and 68020 optimizations  include  re-arrangement  of    the
  261.     code to prevent pipeline stalls, expansion of movem to multiples moves,
  262.     and inversion of most 68000 optimizations that are really bad for  that
  263.     microprocessor (see peephole.doc to see the list).
  264.  
  265. DISTRIBUTION:
  266. ------------
  267.  
  268.     That distribution contains:
  269.  
  270.     - popt:     The main program.
  271.  
  272.     - popt.apurify: The version of    this  program  linked  with APurify
  273.             (If the original program makes  a  guru,  use  that
  274.             version to see, which access  to  memory  makes  an
  275.             APURIFY warning/error, and give me a bug report).
  276.  
  277.     - popt.doc:    This document.
  278.  
  279.     - peephole.doc: The document  listing  the  peephole  optimizations
  280.             made by popt.
  281.  
  282. MISC:
  283. ----
  284.     All the cited marks/logos are property of their respective owner.
  285.  
  286.     I'm am not responsible for the dammage that this  program  can  do.
  287.     Use it at your own risk. It is given "as is". Have in mind  that,  that
  288.     kind of  program  is  not  guaranteed  to  be  safe.  This  archive  is 
  289.     copyrighted but freeware.  You  can redistribute it for free (or little 
  290.     media cost) provided the archive is kept unadulterated.
  291.  
  292.     It is based initially on the optimizer of the HCC distribution, top
  293.     ((c) Sozobon ltd.), but it has been modified and improved a lot to suit
  294.     my needs. Anyway, it helped me a lot with the data-flow analysis.  Some
  295.     optimizations come also from  the  ASP68K  project    (by  Michael  Glew,
  296.     January  1994,  mglew@laurel.ocs.mq.edu.au),   Pascal   Lauly   (lauly@
  297.     cnam.fr) who helped me a lot for  68040-optimizations),  Loïc  Maréchal
  298.     (marechal@cnam.fr) who  helped  me  for  68020-optimizations,  and from
  299.     other sources I don't remind. I thank them very much, since I'm  not an
  300.     ASM-wizard, they helped me a lot.
  301.  
  302.     That program is about 250Kb and 11600 lines of C code. It has  been
  303.     compiled with the non-registered dcc version of DICE, by Matt DILLON.
  304.  
  305.     This program was  initialy  build  with this configuration: a stock
  306.     A500, KS1.3,  512Kb  CHIP  +  512Kb FAST, one single  diskdrive.   I've
  307.     must have been mad in fact    to  stay with that configuration it takes a
  308.     *VERY*  long  time    to  compile:  Use  the '-revinfo' option to see the
  309.     number of successful compilations and multiply it by 5  mins (actually,
  310.     to compile a file it takes at least 10 mins with my config. ;-). Then I
  311.     think you can see how long    it  is for me to make a full re-compilation
  312.     :-). Now I've upgraded a little bit, but I  must  say  that program can
  313.     still be build with my previous configuration.
  314.  
  315.     You can ask me for the sources via e-mail  (not  too  many requests
  316.     please :-). Note that it is bigger than  250Ko, so think about the size
  317.     of your mailbox first !
  318.  
  319.     I can be reached by:
  320.  
  321.     Electronic Mail:    devulder@info.unicaen.fr
  322.  
  323.     Postal Mail:        M. DEVULDER
  324.                 1, Rue du chateau
  325.                 59380 STEENE
  326.                 FRANCE
  327.  
  328. BUGS:
  329. ----
  330.  
  331.     POPT is unable to expand macros. Thus LIBCALL macro is    treated  as
  332.     an unknown instruction. This modifies register live/death analysis    and
  333.     can avoid some optimizations (unknown instructions  use  all  registers
  334.     for savety !). But the code will certainly be more optimized  than    the
  335.     original, anyway.
  336.  
  337.     POPT doesn't know addressings modes specific for the 68020+. If  it
  338.     finds such an  unknown  addressing    mode,  it  will  output  a  warning
  339.     message, and will do no optimization on that mode. But  it    won't  fail
  340.     because it didn't know an adressing mode or an instruction.  The  '-ni'
  341.     option does not allow POPT to recognize those opcodes. It just tells it
  342.     to use new-opcodes for output.
  343.  
  344.     POPT works better on compiler generated code. Code written by  hand
  345.     are  usually  very    powerfull  and    well  optimized  anyway  (usage  of
  346.     automatically set flags). On that kind of writing/optimizations POPT is
  347.     likely to create a bugged code, even if the '-s' option is  used  (POPT
  348.     did not detail flags, and some code  rely  on  instructions  that  only
  349.     touch a part of the status register). Try and  test  heavily  to  check
  350.     before using a POPT'ed code of that kind (doing  the  optimizations  by
  351.     yourself instead is far more safer).
  352.  
  353.     You should have in mind that if you use safe option and safe  setup
  354.     (for -cs, -cr, -ru), many optimizations will not be done. I think  that
  355.     you can safely not use the -s option if the code is generated  by  a  C
  356.     compiler (those are not clever enough to use very  smart  optimizations
  357.     (differenciation half data registers,  taking  into  account  automatic
  358.     flags setting/preservations through instructions, for example)).
  359.  
  360.     Beware that if your code is using half-registers, POPT is likely to
  361.     produce a buggy code, because it does not care about lower/higher  word
  362.     of a register. So avoid putting things in registers high-word,  because
  363.     they'll be probably scratched by some optimization.  In  fact  that  is
  364.     only true if your code was written by hand. (I don't think  a  compiler
  365.     can use half-registers to store data).
  366.